5


Окно списков и списки данных

Поговорим о списках. В VB реализованы два элемента управления, работающие со списками каких-то данных - ListBox (окно со списком) и ComboBox (комбинированное окно со списком).


Видно, что эти элементы отличаются: окно со списком предлагает выбор какого-то элемента из списка, а комбинированное окно дает возможность либо выбрать из существующего списка либо ввести свои данные. Все это связано с теми задачами, для которых предназначены эти элементы. Например, если у нас есть список языков, с которыми может работать наша программа, то естественно, что это - окно со списком; а если у нас происходит регистрация места работы пользователя с помощью готового списка (школьник, студент, рабочий и пр.), то это - комбинированный список, т.к. у пользователя может быть совершенно специфическое место работы и он захочет ввести его название.


Разберем свойства элемента ListBox - окна со списком:

1) Name - имя окна списка.
2) Columns - число столбцов в окне списка. Если columns=0, то список располагается в одном окне, а если columns=1, то элементы располагаются в соответствующем числе столбцов.
3) IntegralHeight - логическое свойство, разрешающее или запрещающее частичный показ в окне элемента, не помещающегося в окне.
4) MultiSelect - задает правило выбора элементов из списка: 0 - пользователь может выбирать только один элемент, 1 - более одного элемента, 2 - более одного элемента с использованием клавиш Shift и Ctrl.
5) Sorted - логическое свойство, определяющее расположение элементов в списке: сортированы по алфавиту или нет.
6) Style - логическое свойство, определяющее формат окна со списком: с квадратиками для "галочек" или без.

Разберем методы элемента ListBox - окна со списком:

1) .AddItem - добавляет элемент в список.
2) .Clear - удаляет все элементы из списка (очистка списка).
3) .RemoveItem - удаляет текущий элемент из списка.
4) .List(n) - выдает значение произвольного элемента списка.
5) .ListIndex - выдает индекс выбранного элемента.
6) .Text - выдает текст (содержимое) выбранного элемента списка.
7) .NewIndex - выдает индекс последнего выбранного элемента списка. Метод имеет смысл в том случае, если пользователь выбрал более одного элемента.
8) .ItemData(Index) - присваивает элементу с указанным индексом число, которое становится связанным с этим элементом.
9) .ListCount - выдает число элементов в списке.
10) .Selected - логический метод, возвращает True или False в зависимости от того, выбрал пользователь элемент из списка или нет.

Замечание. Возникает естественный вопрос: почему у такого простого элемента так много свойств и методов? (И как ими пользоваться?) Всё определяется жизнью, т.е. теми задачами, которые возникают при работе со списками - добавить новый элемент, удалить текущий, узнать, сколько элементов в списке, найти по индексу элемента сам элемент (и наоборот), и т.д.

Лучше всего свойства и методы окна со списком будут нами поняты при разборе примера. Пусть требуется создать программу для туристического агентства, в котором клиенту предлагается список городов для посещения. Каждый город имеет свою цену, поэтому пользователь, отмечающий галочками города, должен сразу же видеть стоимость своего "вояжа". Для гибкости программы попробуем предусмотреть в ней возможность динамического ввода новых городов (с ценами их посещения) в список. Общий вид приложения может быть примерно таким:

На форме присутствуют следующие элементы: 1) List1 - окно со списком; 2) Label1, Label2, Label3 - метки для вывода вспомогательной информации ("Город", "Цена", "Label3" - метка с текстом по умолчанию, мы будем выводить в неё стоимость выбранного тура по городам); 3) txtCity, txtManyCity - текстовые она для возможного ввода названия города и цены его посещения; 4) cmdAddCity, cmdExit - командные кнопки для добавления города в список и выход из программы.

Кстати, вы заметили, что в нашем списке уже присутствуют некоторые города? Эти города являются нашими неизменными предложениями и должны появляться при запуске приложения всегда. Как это сделать? Необходимо поместить элементы нашего списка (т.к. мы не называли его явно, то он имеет имя List1) в процедуру Form_Load(), которая выполнятся при загрузке формы приложения (т.е., грубо говоря, при запуске). Более того, каждый раз при добавлении в список названия города мы будем связывать с ним число, равное стоимости посещения этого города - благо на это есть метод .ItemData(index). Таким образом, процедура имеет вид:

Rem При загрузке формы
	Private Sub Form_Load()
	List1.AddItem "Берлин"
	List1.ItemData(0) = 11
	List1.AddItem "Берн"
	List1.ItemData(1) = 22
	List1.AddItem "Париж"
	List1.ItemData(2) = 33
	List1.AddItem "Марсель"
	List1.ItemData(3) = 44
	List1.AddItem "Копенгаген"
	List1.ItemData(4) = 55
	List1.AddItem "Осло"
	List1.ItemData(5) = 66
	List1.AddItem "Лондон"
	List1.ItemData(6) = 77
	List1.AddItem "Ливерпуль"
	List1.ItemData(7) = 88
	m = 0
End Sub

Разберемся с процедурой добавления нового города с ценой его посещения, т.е. с процедурой cmdAddCity_Click(). В ней должны происходить два действия: 1) к списку элементов надо добавить название города из текстового окна txtCity; 2) с добавленным элементом списка надо связать число, которое находится в текстовом окне txtManyCity.

Rem Добавление нового города
	Private Sub cmdAddCity_Click()
	List1.AddItem txtCity
	List1.ItemData(List1.ListCount - 1) = Val(txtManyCity)
End Sub

Замечание. Обратите внимание, для того, чтобы выяснить индекс элемента, с которым связывается число, мы из числа всех элементов списка (.ListCount) вычитаем единицу. Это сделано потому, что элементы списка нумеруются с 0 (нуля) и если в списке n элементов, то последний имеет номер (n-1). Кроме того, так как число, введенное в поле txtManyCity фактически является строкой, то при присваивании его необходимо перевести в число функцией Val(). Интересно, что если работник туристической фирмы ошибется и введет вместо числа, связанного с городом, строку, то программа интерпретирует ее как число 0 (ноль). Как вам такой вариант?

Теперь займемся самым главным: обработкой выбора городов. Вы заметили в процедуре загрузке формы Form_Load() инициализацию переменной m? В ней мы будем накапливать стоимость путешествия - пока она равна 0, т.к. никакие города еще не выбраны, но пришло время кликать на элементах списка.

Option Explicit
Const s = "Ваше путешествие будет стоить вам ($) - "
Dim m As Double

Rem Выбор элемента
Private Sub List1_ItemCheck(Item As Integer)
If List1.Selected(Item) = True Then 
                                 m = m + List1.ItemData(Item) 
                               Else 
                                 m = m - List1.ItemData(Item)
End If
Label3 = s & m
End Sub

Замечание. Прежде всего, отметим, что при описании глобальных переменных мы ввели константу - строку s и переменную типа double - m. Из всех процедур, связанных с элементом List1, нам больше всего подошла процедура List1_ItemChek(Item As Integer). Хотя, если посмотреть на их список напротив элемента List1, то количество процедур несколько шокирует.

Процедура List1_ItemCheck (выбор элемента из списка List1) хороша тем, что имеет приходящий параметр - целое число Item, которое равно индексу выбранного элемента. Таким образом, мы сразу знаем какое число необходимо добавить в сумму путешествия (т.е. к числу m) - List1.ItemData(Item). Однако при добавлении стоимости путешествия к числу m есть одна тонкость: если город не был выбран, то его стоимость надо добавить к m, а если город уже был выбран (т.е. "галочка" снимается), то стоимость надо отнять от m. Это достигается в операторе If, в котором проверяется: "правда ли, что элемент списка, на котором только что кликнул пользователь является выбранным, т.е. на нем установилась галочка?" - если это так, то к числу m прибавляется число, связанное с отмеченным элементом списка, если нет - то вычитается. Процедура командной кнопки cmdExit ("Выход") очень проста: в ней происходит закрытие приложения.

Rem Выход из программы
Private Sub cmdExit_Click()
End
End Sub

Разберем свойства элемента ComboBox - комбинированного списка:

Практически такие же, как и у ListBox.

Разберем методы элемента ComboBox - комбинированного списка:

Практически такие же, как и у ListBox.

Естественно, что отличия между этими элементами есть. Свойство Style для элемента ComboBox предполагает три вида окна:

1) 0 (DropDown Combo) - поле с раскрывающимся списком.
2) 1 (Simple Combo) - простое поле ввода со списком.
3) 2 (DrowDown List) - поле ввода со списком, превращающееся в раскрывающийся список, который остается закрытым до тех пор, пока пользователь не раскроет список.




Лучше всего свойства и методы элемента ComboBox можно понять на примере. Допустим, что нам необходимо организовать список из 10 элементов - птиц, которые селятся в нашем регионе, - и он почти готов: в него внесены названия 7 птиц. Пользователю надо лишь ввести недостающие три птицы, причем на форме не должно быть никаких других элементов управления, кроме меток. (Пример несколько надуманный, но если бы вы знали, какие странные примеры иногда подкидывает жизнь...) Итак, форма приложения может иметь вид:

В нашем случае удобно воспользоваться комбинированным окном со свойством Style=1 (simple combo) - простое поле ввода со списком. Мы будем вводить названия птиц и нажимать клавишу Enter (ввод). При загрузке нашего приложения оно должно иметь вид, приведенный выше, т.е. в списке уже должно быть семь птиц. Для реализации этого в процедуру загрузки формы поместим следующие операторы:

Option Explicit
Dim i As Integer

Rem При загрузке формы
	Private Sub Form_Load()
	Combo1.AddItem "Соловей"
	Combo1.AddItem "Зяблик"
	Combo1.AddItem "Малиновка"
	Combo1.AddItem "Сорока"
	Combo1.AddItem "Ворона"
	Combo1.AddItem "Воробей"
	Combo1.AddItem "Синица"
	i = 7
End Sub

Понятно, что переменная i типа integer необходима нам как счетчик числа птиц в списке. Пока она равна 7, но ей еще предстоит накапливаться до 10. Теперь перейдем к существу программы: мы должны организовать процедуру, которая позволит пользователю вводить название новой птицы и жать на Enter, после чего в список приходит это новое название, и переменная i увеличивается на единицу. Так должно происходить три раза (с 7 до 10), а потом можно сделать список недоступным: Combo1.Enabled=False.

Private Sub Combo1_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then
                   Combo1.AddItem Combo1.Text
                   Combo1.Text = ""
                   i = i + 1
                   If i = 10 Then Combo1.Enabled = False
End If
End Sub

Замечание. Процедура Combo1_KeyPress() ("если нажали какую-то клавишу в комбинированном окне") имеет параметр - KeyAscii. Этот параметр - целое число - указывает на код из таблицы ASCII того символа (или их сочетаний), который был нажат пользователем в окне списка. Нам совершенно неинтересно, на что там нажимает пользователь, т.к. главное для нас - не прозевать нажатие клавиши Enter ("ввод"), которая имеет код 13. Именно поэтому мы даем процедуре работать только в том случае, если KeyAscii=13, она: 1) добавляет к списку элементов текст из окна ввода списка; 2) очищает окно ввода для следующей "птицы"; 3) накапливает значение переменной i и проверяет ее на равенство 10: если это так, то самое время сделать элемент Combo1 недоступным пользователю.

Задания по лабораторной работе 5


1. Прочитать и законспектировать работу, проверить пример.
2. Разобрать два дополнительных примера (только для тех, у кого есть пособие и дискета с дополнительными примерами).
3. Выбрать любое отчетное задание: "создать программу, в которой..."
1 пользователь вводит целое число, а в список приходит именно столько элементов последовательности "чисел Фибоначчи" (1,1, сумма двух предыдущих, …);
2 пользователь вводит список своей группы, причем имеет право изменять число столбцов в списке и сортировку по алфавиту;
3 пользователь указывает свои данные (ФИО, возраст, класс компьютера), используя готовые данные из списков или вводя собственные (при нажатии кнопки "Регистрация" в окне сообщения должно возникнуть сообщение "Вы... Все правильно?");
4 4) пользователь перекидывает выбранных футболистов из списков двух клубов (туда и обратно), при этом в метках, показывающих кассу клубов, происходит перерасчет, зависящий от цены на каждого игрока.
5*** Доделать программу про туристические поездки, добавив кнопки "Удалить город" - удаление выбранного города из списка; "Распечатка маршрута" - занесение в текстовый файл списка городов, выбранных пользователем и полная распечатка денег, которые он должен агентству + 5% от стоимости лично вам, как программисту.

Хостинг от uCoz